---
title: Enrutamiento
description: Introducción al enrutamiento en Astro.
i18nReady: true
---
import { FileTree } from '@astrojs/starlight/components';
import RecipeLinks from "~/components/RecipeLinks.astro"
import Since from '~/components/Since.astro'
import ReadMore from '~/components/ReadMore.astro'

Astro utiliza **enrutamiento basado en archivos** para generar las URLs finales según el contenido de la carpeta `src/pages/`. 

## Navegando entre páginas

Astro usa elementos HTML estándar [`<a>`](https://developer.mozilla.org/es/docs/Web/HTML/Element/a) para navegar entre rutas. No se proporciona ningún componente `<Link>` específico en Astro.

```astro title="src/pages/index.astro"
<p>¡Leer más <a href="/about/">sobre</a> Astro!</p>
```

## Rutas estáticas

Los [componentes página](/es/basics/astro-pages/) `.astro` así como los archivos Markdown y MDX (`.md`, `.mdx`) dentro del directorio `src/pages/` **se convierten automáticamente en páginas de tu sitio web**. La ruta de cada página corresponde a su ruta y nombre de archivo dentro del directorio `src/pages/`.

```diff
# Ejemplo: Rutas estáticas
src/pages/index.astro        -> mysite.com/
src/pages/about.astro        -> mysite.com/about
src/pages/about/index.astro  -> mysite.com/about
src/pages/about/me.astro     -> mysite.com/about/me
src/pages/posts/1.md         -> mysite.com/posts/1
```

:::tip
¡No hay una "configuración de enrutamiento" separada para mantener en un proyecto Astro! Cuando se agrega un archivo al directorio `src/pages`, se crea automáticamente una nueva ruta. En compilaciones estáticas, puedes personalizar el formato de salida del archivo usando la opción de configuración [`build.format`](/es/reference/configuration-reference/#buildformat)
:::

## Rutas dinámicas

Un archivo de página Astro puede especificar parámetros de ruta dinámicos en su nombre para generar múltiples páginas emparejadas. Por ejemplo, `src/pages/authors/[author].astro` que generará una página por cada autor en tu blog. `author` se convierte en un _parámetro_ al que puedes acceder dentro de la página.

En el modo de generación estático por defecto de Astro, estas páginas serán generadas en tiempo de compilación, así que deberías definir previamente la lista de `author`s para ese archivo. En modo SSR, se generará una página bajo petición para cada ruta que coincida.

### Modo Estático (SSG)

Debido a que todas las rutas deben definirse en tiempo de compilación, una ruta dinámica debe exportar una función `getStaticPaths()` que devuelva un array de objetos con una propiedad `params`. Cada uno de estos objetos generará su ruta correspondiente.

`[dogs].astro` define el parámetro dinámico `dog` en su nombre de archivo, así que los objetos devueltos por `getStaticPaths()` deben incluir `dog` en sus `params`. De esta manera la página puede acceder a este parámetro por medio de `Astro.params`.

```astro title="src/pages/dogs/[dog].astro"
---
export function getStaticPaths() {
  return [
    {params: {dog: 'clifford'}},
    {params: {dog: 'rover'}},
    {params: {dog: 'spot'}},
  ];
}

const { dog } = Astro.params;
---
<div>¡Buen chico, {dog}!</div>
```

Esto generará tres páginas: `/dogs/clifford`, `/dogs/rover` y `/dogs/spot`, cada una mostrando el nombre de perro correspondiente.

El nombre de archivo puede incluir múltiples parámetros, los cuales deben estar todos incluidos en los objetos `params` de `getStaticPaths()`:

```astro title="src/pages/[lang]-[version]/info.astro"
---
export function getStaticPaths () {
 return [
    {params: {lang: 'en', version: 'v1'}},
    {params: {lang: 'fr', version: 'v2'}},
  ];
}

const { lang, version } = Astro.params;
---
...
```

Esto generará `/en-v1/info` y `/fr-v2/info`.

Los parámetros pueden incluirse en distintas partes del path. Por ejemplo, el archivo `src/pages/[lang]/[version]/info.astro` con la misma `getStaticPaths()` arriba generará las rutas `/en/v1/info` y `/fr/v2/info`.

<ReadMore>Lee más sobre [`getStaticPaths()`](/es/reference/api-reference/#getstaticpaths).</ReadMore>

<RecipeLinks slugs={["es/recipes/i18n"]} />

#### Parámetros Rest

Si necesitas más flexibilidad en el enrutamiento de la URL, puedes usar un [parámetro rest](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Functions/rest_parameters) (`[...param]`) en el nombre de archivo `.astro` para emparejar rutas de archivos de cualquier profundidad:

```astro title="src/pages/sequences/[...path].astro"
---
export function getStaticPaths() {
  return [
    {params: {path: 'uno/dos/tres'}},
    {params: {path: 'cuatro'}},
    {params: {path: undefined }}
  ]
}

const { path } = Astro.params;
---
...
```

Esto generará `/sequences/uno/dos/tres`, `/sequences/cuatro` y `/sequences`. (Definir el parámetro restante como `undefined` permite emparejar con la página del nivel más alto.)

Los parámetros rest pueden usarse con **otros parámetros nombrados**. Por ejemplo, el visor de archivos de GitHub puede ser representado con la siguiente ruta dinámica:

```
/[org]/[repo]/tree/[branch]/[...file]
```

En este ejemplo, una solicitud a `/withastro/astro/tree/main/docs/public/favicon.svg` daría como resultado los siguientes parámetros con nombre:

```js
{
	org: 'withastro',
	repo: 'astro',
	branch: 'main',
	file: 'docs/public/favicon.svg'
}
```

#### Ejemplo: Páginas dinámicas en múltiples niveles

En el siguiente ejemplo, un parámetro rest (`[...slug]`) y la característica [`props`](/es/reference/api-reference/#transferencia-de-datos-con-props) de `getStaticPaths()` para generar páginas para _slugs_ de diversa profundidad.

```astro title="src/pages/[...slug].astro"
---
export async function getStaticPaths() {
  const pages = [
    {
      slug: undefined,
      title: "Tienda de Astro",
      text: "¡Te damos la bienvenida a la tienda de Astro!",
    },
    {
      slug: "products",
      title: "Productos de Astro",
      text: "Tenemos muchos productos para ti",
    },
    {
      slug: "products/astro-handbook",
      title: "El libro definitivo de Astro",
      text: "Si quieres aprender sobre Astro, debes leer este libro.",
    },
  ];
  return pages.map(({ slug, title, text }) => {
    return {
      params: { slug },
      props: { title, text },
    };
  });
}
const { title, text } = Astro.props;
---
<html>
  <head>
    <title>{title}</title>
  </head>
  <body>
    <h1>{title}</h1>
    <p>{text}</p>
  </body>
</html>
```

### Modo Servidor (SSR)
En el [modo SSR](/es/guides/server-side-rendering/), las rutas dinámicas se definen de la misma manera: incluyendo `[param]` o `[...path]` en corchetes a los nombres de tus archivos para emparejar con strings o paths arbitrarios. Pero, como esas rutas no se compilan con anticipación, la página va a servirse con cualquier ruta que coincida. Como estas no son rutas "estáticas", no debemos usar `getStaticPaths`.

```astro title="src/pages/resources/[resource]/[id].astro"
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}<h1>
```
Esta página será servida para cualquier valor de `resource` y `id`: `resources/users/1`, `resources/colors/blue`, etc.

#### Modificando el ejemplo `[...slug]` para SSR

Debido a que las páginas SSR no pueden usar `getStaticPaths`, no pueden recibir props. El [ejemplo anterior](#ejemplo-páginas-dinámicas-en-múltiples-niveles) puede ser adaptado para el modo SSR buscando el valor del parámetro `slug` en un objeto. Si la ruta está en la raíz ("/"), el parámetro slug va a ser `undefined`. Si el valor no existe en el objeto, redirigiremos a una página 404.

```astro title="src/pages/[...slug].astro"
---
const pages = [
	{
		slug: undefined,
		title: 'Tienda de Astro',
		text: '¡Te damos la bienvenida a la tienda de Astro!',
	},
	{
		slug: 'products',
		title: 'Productos de Astro',
		text: 'Tenemos muchos productos para ti',
	},
	{
		slug: 'products/astro-handbook',
		title: 'El libro definitivo de Astro',
		text: 'Si quieres aprender sobre Astro, debes leer este libro.',
	}
];

const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
  <title>{title}</title>
</head>
<body>
  <h1>{title}</h1>
  <p>{text}</p>
</body>
</html>
```

## Redirecciones

A veces necesitarás redirigir a tus lectores a una nueva página, ya sea de forma permanente debido a cambios en la estructura de tu sitio o como respuesta a una acción como iniciar sesión en una ruta autenticada.

Puedes definir reglas para [redirigir a los usuarios a páginas movidas permanentemente](#redirecciones-configuradas) en tu configuración de Astro. O puedes redirigir a los [usuarios dinámicamente](#redirecciones-dinámicas) a medida que utilizan tu sitio.

### Redirecciones configuradas


<Since v="2.9.0" />

Puedes especificar un mapeo de redirecciones permanentes en la configuración de Astro con el valor `redirects`. Para la mayoría de las redirecciones, esto es un mapeo de una ruta antigua a la nueva ruta:

```js title="astro.config.mjs" {4-6}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': '/new-page'
  }
});
```

Estas redirecciones siguen las mismas reglas que las rutas basadas en archivos. Se permiten rutas dinámicas siempre y cuando tanto las rutas nuevas como las antiguas contengan los mismos parámetros, por ejemplo:

```js
{
  "/blog/[...slug]": "/articles/[...slug]"
}
```

Usando SSR o un adaptador estático, también puedes proporcionar un objeto como valor, lo que te permite especificar el código de estado (`status`) además del nuevo destino (`destination`):

```js title="astro.config.mjs" {5-8}
import { defineConfig } from 'astro/config';

export default defineConfig({
  redirects: {
    '/old-page': {
      status: 302,
      destination: '/new-page'
    }
  }
});
```

Al ejecutar `astro build`, Astro generará archivos HTML con la etiqueta [meta refresh](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#examples) de forma predeterminada. En cambio, los adaptadores compatibles escribirán el archivo de configuración del host con las redirecciones.

Por defecto, el código de estado es `301`. Si estás generando archivos HTML estáticos, el servidor no utiliza el código de estado.

### Redirecciones dinámicas

En el objeto global `Astro`, el método `Astro.redirect` te permite redirigir a otra página de forma dinámica. Puedes hacer esto después de verificar si el usuario ha iniciado sesión obteniendo su sesión desde una cookie.

```astro title="src/pages/account.astro" {8}
---
import { isLoggedIn } from '../utils';

const cookie = Astro.request.headers.get('cookie');

// Si el usuario no ha iniciado sesión, redirígelos a la página de inicio de sesión
if (!isLoggedIn(cookie)) {
  return Astro.redirect('/login');
}
---
<html>
  <!-- Aquí está la página... -->
</html>
```


## Orden de prioridad de rutas

Es posible que varias rutas definidas intenten construir la misma ruta de URL. Por ejemplo, todas estas rutas podrían construir `/posts/create`:

<FileTree>
- src/pages/
  - [...slug].astro
  - posts/
    - create.astro
    - [page].astro
    - [pid].ts
    - [...slug].astro
</FileTree>

Astro necesita saber qué ruta debe usarse para construir la página. Para ello, los ordena de acuerdo con las siguientes reglas en orden:

- Las rutas con más segmentos de ruta tendrán prioridad sobre las rutas con menos parámetros. En el ejemplo anterior, todas las rutas bajo `/posts/` tienen prioridad sobre `/[...slug].astro` en la raíz.
- Las rutas estáticas sin parámetros de ruta tendrán prioridad sobre las rutas dinámicas. Por ejemplo, `/posts/create.astro` tiene prioridad sobre todas las demás rutas del ejemplo.
- Las rutas dinámicas que usan parámetros nombrados tienen prioridad sobre los parámetros restantes. Por ejemplo, `/posts/[page].astro` tiene prioridad sobre `/posts/[...slug].astro`.
- Las rutas dinámicas pre-renderizadas tienen prioridad sobre las rutas dinámicas del servidor.
- Los endpoints tienen prioridad sobre las páginas.
- Si ninguna de las reglas anteriores decide el orden, las rutas se ordenan alfabéticamente según la configuración regional predeterminada de tu instalación de Node.

Dado el ejemplo anterior, aquí hay algunos ejemplos de cómo las reglas harán coincidir una URL solicitada con la ruta utilizada al compilar el HTML:

- `pages/posts/create.astro` - Solo construirá `/posts/create`
- `pages/posts/[pid].ts` - Construirá `/posts/abc`, `/posts/xyz`, etc. Pero no `/posts/create`
- `pages/posts/[page].astro` - Construirá `/posts/1`, `/posts/2`, etc. Pero no `/posts/create`, `/posts/abc` ni `/posts/xyz`
- `pages/posts/[...slug].ts` - Construirá `/posts/1/2`, `/posts/a/b/c`, etc. Pero no `/posts/create`, `/posts/1`, `/posts/abc`, etc.
- `pages/[...slug].astro` - Construirá `/abc`, `/xyz`, `/abc/xyz`, etc. Pero no `/posts/create`, `/posts/1`, `/posts/abc`, , etc.

## Paginación

Astro mantiene la paginación automática integrada para grandes colecciones de datos que deben dividirse en varias páginas. Astro incluirá automáticamente metadatos de paginación como la URL de la página anterior/siguiente, el número total de páginas y más.

Los nombres de rutas paginadas deben usar la misma sintaxis `[corchete]` que una ruta dinámica estándar. Por ejemplo, el nombre de archivo `/astronautas/[page].astro` generará rutas para `/astronautas/1`, `/astronautas/2`, etc., donde `[page]` es el número de página generado.

Puedes usar la función `paginate()` para generar estas páginas para un array de valores como este:

```astro /{ (paginate) }/ /paginate\\(.*\\)/ /(?<=const.*)(page)/ /page\\.[a-zA-Z]+/
---
// src/pages/astronauts/[page].astro
export async function getStaticPaths({ paginate }) {
  const astronautPages = [{
    astronaut: 'Neil Armstrong',
  }, {
    astronaut: 'Buzz Aldrin',
  }, {
    astronaut: 'Sally Ride',
  }, {
    astronaut: 'John Glenn',
  }];
  // Genera páginas para nuestro array de astronautas, con 2 elementos por página
  return paginate(astronautPages, { pageSize: 2 });
}
// Todos los datos paginados se pasan en la prop "page"
const { page } = Astro.props;
---

<!--Muestra el número de página actual. ¡También puedes utilizar Astro.params.page!-->
<h1>Página {page.currentPage}</h1>
<ul>
  <!--Enumera el array con información sobre astronautas-->
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
```

Esto genera las siguientes páginas, con 2 elementos por página:
- `/astronauts/1` - Página 1: muestra "Neil Armstrong" y "Buzz Aldrin"
- `/astronauts/2` - Página 2: Muestra "Sally Ride" y "John Glenn"

### La prop `page`

Cuando usas la función `paginate()`, a cada página se le pasarán los datos a través de una prop `page`. La prop `page` tiene muchas propiedades útiles, pero estas son las más destacadas:
- **page.data** - array que contiene la porción de datos de página que introdujo a la función `paginate()`
- **page.url.next** - enlace a la página siguiente del mismo conjunto de datos
- **page.url.prev** - enlace a la página anterior del mismo conjunto de datos

```astro /(?<=const.*)(page)/ /page\\.[a-zA-Z]+(?:\\.(?:prev|next))?/
---
// src/pages/astronauts/[page].astro
// Paginar la misma lista de objetos { astronaut } como en el ejemplo anterior
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Página {page.currentPage}</h1>
<ul>
  {page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.prev ? <a href={page.url.prev}>Anterior</a> : null}
{page.url.next ? <a href={page.url.next}>Siguiente</a> : null}
```

#### Referencia completa de la API

```ts
interface Page<T = any> {
	/** resultado */
	data: T[];
	/** metadatos */
	/** el recuento del primer elemento de la página, a partir de 0 */
	start: number;
	/** el recuento del último elemento de la página, a partir de 0 */
	end: number;
	/** el número total de resultados */
	total: number;
	/** el número de la página actual, a partir de 1 */
	currentPage: number;
	/** el número de elementos por página (predeterminado: 25) */
	size: number;
	/** el número de la última página */
	lastPage: number;
	url: {
		/** la url de la página actual */
		current: string;
		/** la url de la página anterior (si hay alguna) */
		prev: string | undefined;
		/** la url de la página siguiente (si hay alguna) */
		next: string | undefined;
	};
}
```

### Paginación anidada

Un caso de uso más avanzado de la paginación es la **paginación anidada.** Aquí es cuando la paginación se combina con otros parámetros de rutas dinámicas. Puedes usar la paginación anidada para agrupar la colección paginada por alguna propiedad o etiqueta.

Por ejemplo, si prefieres agrupar las publicaciones de Markdown paginadas por alguna etiqueta, usarás la paginación anidada creando una página `/src/pages/[tag]/[page].astro` que coincida con las siguientes URL:

- `/red/1` (tag=red)
- `/red/2` (tag=red)
- `/blue/1` (tag=blue)
- `/green/1` (tag=green)

La paginación anidada funciona devolviendo un array de resultados `paginate()` de `getStaticPaths()`, uno para cada grupo.

En el siguiente ejemplo, implementaremos la paginación anidada para crear las URL enumeradas anteriormente:

```astro /(?:[(]|=== )(tag)/ "params: { tag }" /const [{ ]*(page|params)/
---
// src/pages/[tag]/[page].astro
export async function getStaticPaths({paginate}) {
  const allTags = ['rojo', 'azul', 'verde'];
  const allPosts = await Astro.glob('../../posts/*.md');
  // Para cada etiqueta, devuelve un resultado de paginate().
  // Asegúrate de pasar `{params: {tag}}` a `paginate()`
  // Así Astro sabrá qué agrupación de etiquetas usar.
  return allTags.flatMap((tag) => {
    const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
    return paginate(filteredPosts, {
      params: { tag },
      pageSize: 10
    });
  });
}
const { page } = Astro.props;
const params = Astro.params;
```


## Excluyendo páginas

Puedes excluir la generación de páginas o directorios añadiendo el prefijo (`_`). Los archivos con el prefijo `_` no serán reconocidos por el router y no serán generados en el directorio `dist/`.

Puedes usar esto para inhabilitar páginas temporalmente y también para poner tests, utilidades y componentes en la misma carpeta junto a sus páginas correspondientes.

En este ejemplo, solo `src/pages/index.astro` y `src/pages/posts/post1.md` serán generados como rutas y archivos `.html`.

<FileTree>
- src/pages/
  - _hidden-directory/
    - page1.md
    - page2.md
  - _hidden-page.astro
  - **index.astro**
  - posts/
    - _SomeComponent.astro
    - _utils.js
    - **post1.md**
</FileTree>
